import pandas as pd
import os
import glob

def load_csv_data(problem_prefix):
    """加载指定问题的CSV数据文件"""
    stats_file = f"{problem_prefix}_统计信息.csv"
    makeup_file = f"{problem_prefix}_化妆师排班表.csv"
    room_file = f"{problem_prefix}_直播间使用情况.csv"
    
    data = {}
    
    # 加载统计信息
    if os.path.exists(stats_file):
        data['stats'] = pd.read_csv(stats_file)
    else:
        print(f"警告: 找不到统计信息文件 {stats_file}")
        data['stats'] = None
    
    # 加载化妆师排班表
    if os.path.exists(makeup_file):
        data['makeup'] = pd.read_csv(makeup_file)
    else:
        print(f"警告: 找不到化妆师排班表文件 {makeup_file}")
        data['makeup'] = None
    
    # 加载直播间使用情况
    if os.path.exists(room_file):
        data['room'] = pd.read_csv(room_file)
    else:
        print(f"警告: 找不到直播间使用情况文件 {room_file}")
        data['room'] = None
    
    return data

def time_to_hours(time_str):
    """将时间字符串转换为小时数"""
    h, m = map(int, time_str.split(':'))
    return h + m / 60

def check_constraints(data, problem_name):
    """检查排班表是否符合约束条件"""
    if data['room'] is None or data['makeup'] is None:
        print("无法检查约束条件: 缺少排班数据")
        return True  # 无法检查，默认通过
    
    violations = []
    
    # 1. 检查直播时间约束
    # 直播间开放时间为早8:00-次日凌晨4:00
    room_df = data['room'].copy()
    if '状态' in room_df.columns and '时间' in room_df.columns:
        # 检查是否有在8:00前或次日4:00后开始的直播
        for _, row in room_df[room_df['状态'].str.contains('开始直播', na=False)].iterrows():
            time_h = time_to_hours(row['时间'])
            if time_h < 8 or time_h >= 28:  # 28表示次日4:00
                violations.append(f"违反直播时间约束: 房间{row['房间']}在{row['时间']}开始直播，不在允许的时间范围内")
    
    # 2. 检查化妆师工作时间约束
    # 化妆师工作时间为早7:00-12:00，13:00-17:00
    # 注意：我们只检查化妆师排班表中有化妆师工作的时间段
    makeup_df = data['makeup'].copy()
    if '时间' in makeup_df.columns:
        for _, row in makeup_df.iterrows():
            time_str = row['时间']
            time_h = time_to_hours(time_str)
            
            # 检查是否有化妆师在这个时间段工作
            has_working_artist = False
            for col in makeup_df.columns:
                if '化妆师' in col and row[col] != '休息' and not pd.isna(row[col]):
                    has_working_artist = True
                    break
            
            # 只检查有化妆师工作的时间段
            if has_working_artist and not ((7 <= time_h < 12) or (13 <= time_h < 17)):
                violations.append(f"违反化妆师工作时间约束: 在{time_str}安排了化妆工作，不在允许的时间范围内")
    
    # 3. 检查每个时间窗口的化妆师数量约束
    if '时间' in makeup_df.columns:
        for _, row in makeup_df.iterrows():
            time_str = row['时间']
            # 计算这个时间段工作的化妆师数量
            working_count = 0
            for col in makeup_df.columns:
                if '化妆师' in col and row[col] != '休息' and not pd.isna(row[col]):
                    working_count += 1
            
            max_makeup_artists = 7 if problem_name == '问题1_Part1' else 15
            if working_count > max_makeup_artists:
                violations.append(f"违反化妆师数量约束: 在{time_str}同时有{working_count}名化妆师工作，超过了最大限制{max_makeup_artists}人")
    
    # 4. 检查化妆后等待时间约束
    # 化妆后5小时内必须进入直播室
    if '状态' in room_df.columns and '时间' in room_df.columns:
        # 创建一个字典来跟踪每个主播的化妆和直播记录
        streamer_records = {}
        
        # 按时间排序
        room_df = room_df.sort_values(by=['时间'])
        
        # 遍历所有记录，记录每个主播的化妆和直播时间
        for _, row in room_df.iterrows():
            room = row['房间']
            time_str = row['时间']
            status = row['状态']
            time_hour = time_to_hours(time_str)
            
            if room not in streamer_records:
                streamer_records[room] = []
            
            # 记录活动类型和时间
            if '开始化妆' in status:
                streamer_records[room].append(('化妆', time_str, time_hour))
            elif '开始直播' in status or '开始带妆直播' in status:
                streamer_records[room].append(('直播', time_str, time_hour))
        
        # 检查每个主播的化妆和直播记录
        for room, records in streamer_records.items():
            # 按时间排序记录
            records.sort(key=lambda x: x[2])
            
            # 检查每次化妆后是否在5小时内开始直播
            for i in range(len(records) - 1):
                current_record = records[i]
                next_record = records[i + 1]
                
                # 如果当前记录是化妆，下一个记录是直播
                if current_record[0] == '化妆' and next_record[0] == '直播':
                    makeup_hour = current_record[2]
                    broadcast_hour = next_record[2]
                    
                    # 处理跨天的情况
                    if broadcast_hour < makeup_hour:
                        broadcast_hour += 24  # 加上24小时表示次日
                    
                    time_diff = broadcast_hour - makeup_hour
                    
                    if time_diff > 5.5:
                        violations.append(f"违反化妆后等待时间约束: 房间{room}在{current_record[1]}化妆，但在{next_record[1]}才开始直播，等待时间为{time_diff:.2f}小时，超过了5.5小时的限制")
    
    # 5. 检查直播间使用时间约束
    # 同一直播间开始直播后6.5小时内没有其他人进来直播
    if '状态' in room_df.columns and '时间' in room_df.columns and '房间' in room_df.columns:
        # 创建一个字典来跟踪每个直播间的使用情况
        room_usage = {}
        
        # 按时间排序
        room_df = room_df.sort_values(by=['时间'])
        
        # 遍历所有记录，记录每个直播间的使用情况
        for _, row in room_df.iterrows():
            room_id = row['房间']
            time_str = row['时间']
            status = row['状态']
            time_hour = time_to_hours(time_str)
            
            # 只关注开始直播的记录
            if '开始直播' in status or '开始带妆直播' in status:
                if room_id not in room_usage:
                    room_usage[room_id] = []
                
                # 检查是否违反直播间使用时间约束
                for prev_time, prev_hour in room_usage[room_id]:
                    # 处理跨天的情况
                    curr_hour = time_hour
                    if curr_hour < prev_hour:
                        curr_hour += 24  # 加上24小时表示次日
                    
                    # 检查时间差是否小于6.5小时
                    if curr_hour - prev_hour < 6.5:
                        violations.append(f"违反直播间使用时间约束: 房间{room_id}在{prev_time}开始直播，但在{time_str}又有新的直播开始，间隔仅为{curr_hour - prev_hour:.2f}小时，小于6.5小时的限制")
                
                # 记录当前直播开始时间
                room_usage[room_id].append((time_str, time_hour))
    
    # 输出违反约束的情况
    if violations:
        print(f"\n发现{len(violations)}个违反约束条件的情况:")
        for i, violation in enumerate(violations, 1):
            print(f"{i}. {violation}")
        return False
    else:
        print("✓ 未发现违反约束条件的情况")
        return True

def validate_problem1_part1(data):
    """验证问题1 Part1的结果"""
    print("\n===== 验证问题1 Part1 =====")
    
    if data['stats'] is None:
        print("无法验证: 缺少统计信息")
        return False
    
    # 提取关键指标
    try:
        total_streams = data['stats']['总直播场次'].values[0]
        streams_with_makeup = data['stats']['带妆直播场次'].values[0]
        makeup_rate = data['stats']['化妆率'].values[0]
        monthly_profit = data['stats']['月净利润'].values[0]
        
        # 验证化妆率是否大于等于60%
        if makeup_rate >= 0.6:
            print(f"✓ 化妆率为 {makeup_rate:.2%}，满足大于等于60%的要求")
        else:
            print(f"✗ 化妆率为 {makeup_rate:.2%}，不满足大于等于60%的要求")
            return False
        
        # 验证化妆师数量是否为7人
        if data['makeup'] is not None:
            makeup_artists = [col for col in data['makeup'].columns if '化妆师' in col]
            num_makeup_artists = len(makeup_artists)
            if num_makeup_artists == 7:
                print(f"✓ 化妆师数量为 {num_makeup_artists}，符合要求")
            else:
                print(f"✗ 化妆师数量为 {num_makeup_artists}，不符合要求（应为7人）")
                return False
        
        # 验证月净利润计算是否正确
        expected_profit = total_streams * 4000 - 7 * 9000
        if abs(monthly_profit - expected_profit) < 1:  # 允许小的浮点数误差
            print(f"✓ 月净利润 {monthly_profit} 计算正确")
        else:
            print(f"✗ 月净利润 {monthly_profit} 计算可能有误（期望值: {expected_profit}）")
            return False
        
        # 检查约束条件
        constraints_passed = check_constraints(data, '问题1_Part1')
        if not constraints_passed:
            print("✗ 排班表存在违反约束条件的情况")
            return False
        
        print(f"✓ 问题1 Part1验证通过")
        return True
    
    except Exception as e:
        print(f"验证过程中出错: {e}")
        return False

def validate_problem1_part2(data):
    """验证问题1 Part2的结果"""
    print("\n===== 验证问题1 Part2 =====")
    
    if data['stats'] is None:
        print("无法验证: 缺少统计信息")
        return False
    
    # 提取关键指标
    try:
        total_streams = data['stats']['总直播场次'].values[0]
        streams_with_makeup = data['stats']['带妆直播场次'].values[0]
        makeup_rate = data['stats']['化妆率'].values[0]
        monthly_profit = data['stats']['月净利润'].values[0]
        
        # 验证化妆率是否为100%
        if abs(makeup_rate - 1.0) < 0.01:  # 允许小的浮点数误差
            print(f"✓ 化妆率为 {makeup_rate:.2%}，满足100%的要求")
        else:
            print(f"✗ 化妆率为 {makeup_rate:.2%}，不满足100%的要求")
            return False
        
        # 验证化妆师数量是否合理
        if data['makeup'] is not None:
            makeup_artists = [col for col in data['makeup'].columns if '化妆师' in col]
            num_makeup_artists = len(makeup_artists)
            if 7 <= num_makeup_artists <= 75:
                print(f"✓ 化妆师数量为 {num_makeup_artists}，在合理范围内")
            else:
                print(f"✗ 化妆师数量为 {num_makeup_artists}，不在合理范围内（应为7-75人）")
                return False
            
            # 验证月净利润计算是否正确
            expected_profit = total_streams * 4000 - num_makeup_artists * 9000
            if abs(monthly_profit - expected_profit) < 1:  # 允许小的浮点数误差
                print(f"✓ 月净利润 {monthly_profit} 计算正确")
            else:
                print(f"✗ 月净利润 {monthly_profit} 计算可能有误（期望值: {expected_profit}）")
                return False
        
        # 检查约束条件
        constraints_passed = check_constraints(data, '问题1_Part2')
        if not constraints_passed:
            print("✗ 排班表存在违反约束条件的情况")
            return False
        
        print(f"✓ 问题1 Part2验证通过")
        return True
    
    except Exception as e:
        print(f"验证过程中出错: {e}")
        return False

def validate_problem2(data):
    """验证问题2的结果"""
    print("\n===== 验证问题2 =====")
    
    if data['stats'] is None:
        print("无法验证: 缺少统计信息")
        return False
    
    # 提取关键指标
    try:
        total_streams = data['stats']['总直播场次'].values[0]
        streams_with_makeup = data['stats']['带妆直播场次'].values[0]
        makeup_rate = data['stats']['化妆率'].values[0]
        monthly_profit = data['stats']['月净利润'].values[0]
        
        # 验证化妆师数量是否为15人
        if data['makeup'] is not None:
            makeup_artists = [col for col in data['makeup'].columns if '化妆师' in col]
            num_makeup_artists = len(makeup_artists)
            if num_makeup_artists == 15:
                print(f"✓ 化妆师数量为 {num_makeup_artists}，符合要求")
            else:
                print(f"✗ 化妆师数量为 {num_makeup_artists}，不符合要求（应为15人）")
                return False
        
        # 验证月净利润计算是否正确
        expected_profit = total_streams * 4000 + streams_with_makeup * 800 - 15 * 9000
        if abs(monthly_profit - expected_profit) < 1:  # 允许小的浮点数误差
            print(f"✓ 月净利润 {monthly_profit} 计算正确")
        else:
            print(f"✗ 月净利润 {monthly_profit} 计算可能有误（期望值: {expected_profit}）")
            return False
        
        # 检查约束条件
        constraints_passed = check_constraints(data, '问题2')
        if not constraints_passed:
            print("✗ 排班表存在违反约束条件的情况")
            return False
        
        print(f"✓ 问题2验证通过")
        return True
    
    except Exception as e:
        print(f"验证过程中出错: {e}")
        return False

def validate_problem3(data):
    """验证问题3的结果"""
    print("\n===== 验证问题3 =====")
    
    if data['stats'] is None:
        print("无法验证: 缺少统计信息")
        return False
    
    # 提取关键指标
    try:
        total_streams = data['stats']['总直播场次'].values[0]
        streams_with_makeup = data['stats']['带妆直播场次'].values[0]
        makeup_rate = data['stats']['化妆率'].values[0]
        monthly_profit = data['stats']['月净利润'].values[0]
        
        # 验证化妆师数量是否为15人
        if data['makeup'] is not None:
            makeup_artists = [col for col in data['makeup'].columns if '化妆师' in col]
            num_makeup_artists = len(makeup_artists)
            if num_makeup_artists == 15:
                print(f"✓ 化妆师数量为 {num_makeup_artists}，符合要求")
            else:
                print(f"✗ 化妆师数量为 {num_makeup_artists}，不符合要求（应为15人）")
                return False
        
        # 验证高级主播比例
        if data['room'] is not None:
            # 检查是否有高级主播标记
            has_senior_streamer = data['room']['状态'].str.contains('高级主播').any()
            if has_senior_streamer:
                # 计算高级主播数量
                senior_streams = data['room'][data['room']['状态'].str.contains('高级主播')].shape[0]
                senior_ratio = senior_streams / total_streams
                
                if senior_ratio <= 0.1:
                    print(f"✓ 高级主播比例为 {senior_ratio:.2%}，不超过10%")
                else:
                    print(f"✗ 高级主播比例为 {senior_ratio:.2%}，超过了10%的限制")
                    return False
            else:
                print("⚠ 未检测到高级主播标记，无法验证高级主播比例")
        
        # 验证时间段收益系数
        if data['room'] is not None:
            # 检查是否有黄金时段和凌晨时段的直播
            golden_hours = ['18:00', '18:30', '19:00', '19:30', '20:00', '20:30', '21:00', '21:30']
            late_night = ['22:00', '22:30', '23:00', '23:30', '0:00', '0:30', '1:00', '1:30', '2:00', '2:30', '3:00', '3:30']
            
            has_golden_hour = data['room']['时间'].isin(golden_hours).any()
            has_late_night = data['room']['时间'].isin(late_night).any()
            
            if has_golden_hour and has_late_night:
                print("✓ 排班表包含黄金时段和凌晨时段的直播")
            else:
                if not has_golden_hour:
                    print("⚠ 未检测到黄金时段(18:00-22:00)的直播")
                if not has_late_night:
                    print("* 未检测到凌晨时段的直播(收益较低)")
        
        # 检查约束条件
        constraints_passed = check_constraints(data, '问题3')
        if not constraints_passed:
            print("✗ 排班表存在违反约束条件的情况")
            return False
        
        print(f"✓ 问题3验证通过")
        return True
    
    except Exception as e:
        print(f"验证过程中出错: {e}")
        return False

def validate_all_results():
    """验证所有问题的结果"""
    print("开始验证实验结果...")
    
    # 查找所有CSV文件
    csv_files = glob.glob("*_统计信息.csv")
    problem_prefixes = set([f.split('_统计信息.csv')[0] for f in csv_files])
    
    if not problem_prefixes:
        print("未找到任何CSV文件，请先运行export_to_csv.py导出数据")
        return
    
    results = {}
    
    # 验证问题1 Part1
    if '问题1_Part1' in problem_prefixes:
        data = load_csv_data('问题1_Part1')
        results['问题1_Part1'] = validate_problem1_part1(data)
    else:
        print("未找到问题1 Part1的数据文件")
    
    # 验证问题1 Part2
    if '问题1_Part2' in problem_prefixes:
        data = load_csv_data('问题1_Part2')
        results['问题1_Part2'] = validate_problem1_part2(data)
    else:
        print("未找到问题1 Part2的数据文件")
    
    # 验证问题2
    if '问题2' in problem_prefixes:
        data = load_csv_data('问题2')
        results['问题2'] = validate_problem2(data)
    else:
        print("未找到问题2的数据文件")
    
    # 验证问题3
    if '问题3' in problem_prefixes:
        data = load_csv_data('问题3')
        results['问题3'] = validate_problem3(data)
    else:
        print("未找到问题3的数据文件")
    
    # 输出总结
    print("\n===== 验证结果总结 =====")
    for problem, passed in results.items():
        status = "通过" if passed else "未通过"
        print(f"{problem}: {status}")

if __name__ == "__main__":
    validate_all_results()
